#include <cnet.h>
#include <string.h>

static  CnetTimerID     lasttimer	= NULLTIMER; /* each node has its timer */

typedef struct{
	char data[MAX_MESSAGE_SIZE]; /* 10240 bytes */
} MSG; /* data type for message */


/**
 * Handles requests from applications to be send over network.
 */
EVENT_HANDLER(application_ready){
	/* local variables */
	CnetAddr dest; /* the destination for the message */
	MSG 	 msg; /* reserve space for the message */
	size_t 	 len = MAX_MESSAGE_SIZE; /* variable for actual message length */

	CHECK(CNET_read_application(&dest,(char *)&msg,&len));/* read in data from application */
	CHECK(CNET_disable_application(dest)); /* prevent application from sending other messages to same destination */
	CnetTime timeout = len*(CnetTime)8000000 / linkinfo[1].bandwidth; /* compute transmission delay */
	lasttimer = CNET_start_timer(EV_TIMER1, timeout , (CnetData)dest); /* start timer */
	CHECK(CNET_write_physical(1,(char *)&msg,&len)); /* write data onto the link */
}

/**
 * After a send-request has been transmitted over the network, we wait a specific amount of
 * time before we allow the next send-request by an application.
 */
static void timeouts(CnetEvent ev, CnetTimerID timer, CnetData data)
{
    if(timer == lasttimer) { /* if it's the right timer */
    	CHECK(CNET_enable_application((CnetAddr)data)); /* allow the application to send more messages */
    }
}

EVENT_HANDLER(physical_ready){	
	/* local variables */
	MSG 	msg;	/* reserve space for the message */
	size_t 	len	= MAX_MESSAGE_SIZE; /* variable for the actual length */
	int	link	= 1; 
	CHECK(CNET_read_physical(&link, (char *)&msg, &len));/* read in data from link */
	CHECK(CNET_write_application((char *)&msg, &len));/* forward data to application */
}


/**
 * Initialize all nodes with the same code at the beginning of the simulation.
 */
EVENT_HANDLER(reboot_node){
	CHECK(CNET_set_handler(EV_APPLICATIONREADY, application_ready, 0));
	CHECK(CNET_set_handler(EV_PHYSICALREADY, physical_ready, 0));
	CHECK(CNET_set_handler(EV_TIMER1, timeouts, 0));
	CHECK(CNET_enable_application(ALLNODES));
}
